using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.IO;

namespace Rest
{
    /// <summary>
    /// Represents an item of data which can be sent to a rest service
    /// </summary>
    /// <remarks>
    /// TODO: 2008-11-13 : Refactor in terms of streams, not Byte arrays -- because
    /// we may be working with huge files.
    /// </remarks>
    public class RestDataItem : IRestDataItem
    {
        #region Properties

        private NameValueCollection attributes;
        private String contentType = "unknown";
        private Byte[] data;
        private String name;

        /// <summary>
        /// A collection attributes for the RestDataItem
        /// </summary>
        /// <remarks>Example usage: Multipart posts</remarks> 
        public NameValueCollection Attributes
        {
            get
            {
                return attributes ?? 
                    (attributes = new NameValueCollection());
            }
            set { attributes = value; }
        }

        /// <summary>
        /// The content type of the data item, example text/plain
        /// </summary>
        public String ContentType
        {
            get { return contentType; }
            set { contentType = value; }
        }

        /// <summary>
        /// The Data associated with the RestDataItem item
        /// </summary>
        public Byte[] GetBytes()
        {
            return data ?? new Byte[0];
        }

        /// <summary>
        /// The number of bytes possessed by the current data item.
        /// Returns 0 if no data exists.
        /// </summary>
        public Int32 Length
        {
            get { return data != null ? data.Length : 0; }
        }

        /// <summary>
        /// The name associated with the RestDataItem item
        /// </summary>
        public String Name
        {
            get { return name; }
            set { name = value; }
        }

        #endregion

        /// <summary>
        /// ctor : String, Byte[]
        /// </summary>
        /// <param name="name">The name of the parameter</param>
        /// <param name="data"></param>
        public RestDataItem(String name, Byte[] data)
        {
            this.name = name;
            this.data = data;
        }

        /// <summary>
        /// ctor: String, Byte[], String
        /// </summary>
        /// <param name="name"></param>
        /// <param name="data"></param>
        /// <param name="contentType"></param>
        public RestDataItem(String name, Byte[] data, String contentType) : 
            this(name, data)
        {
            this.contentType = contentType;
        }

        /// <summary>
        /// ctor : String, FileInfo, String 
        /// Creates a RestDataItem based on the supplied file
        /// </summary>
        /// <param name="file"></param>
        /// <param name="name"></param>
        /// <param name="contentType"></param>
        public RestDataItem(String name, FileInfo file, String contentType)
        {
            // TODO: Don't do this here. Don't throw exceptions in ctor.
            using (MemoryStream memStream = new MemoryStream())
            {
                Byte[] buffer = new Byte[256];

                using (
                    FileStream fileStream = new FileStream(
                        file.FullName, 
                        FileMode.Open,
                        FileAccess.ReadWrite, 
                        FileShare.Read
                    )
                )
                {
                    Int32 bytesRead = 0;

                    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        memStream.Write(buffer, 0, bytesRead);
                    }
                }

                memStream.Flush();

                this.data = memStream.ToArray();
                this.contentType = contentType;
  
                Attributes.Add("name", name);  
                Attributes.Add("filename", System.IO.Path.GetFileName(file.FullName));
            }
        }
    }
}
